home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 3: Developer Tools / Linux Cubed Series 3 - Developer Tools.iso / utils / file / managers / mc-3.2 / mc-3 / mc-3.2.1 / src / mad.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-05-17  |  6.9 KB  |  244 lines

  1. /* The Memory Allocation Debugging system
  2.    Copyright (C) 1994 Janne Kukonlehto.
  3.  
  4.    To use MAD define HAVE_MAD and include "mad.h" in all the *.c files.
  5.  
  6.    This program is free software; you can redistribute it and/or modify
  7.    it under the terms of the GNU General Public License as published by
  8.    the Free Software Foundation; either version 2 of the License, or
  9.    (at your option) any later version.
  10.    
  11.    This program is distributed in the hope that it will be useful,
  12.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.    GNU General Public License for more details.
  15.  
  16.    You should have received a copy of the GNU General Public License
  17.    along with this program; if not, write to the Free Software
  18.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
  19.  
  20. #include <config.h>
  21. #include "mad.h"
  22. #undef malloc
  23. #undef calloc
  24. #undef realloc
  25. #undef xmalloc
  26. #undef strdup
  27. #undef free
  28. #include <stdlib.h>
  29. #include <stdio.h>
  30. #include <string.h>
  31.  
  32. /* Here to avoid non empty translation units */
  33. #ifdef HAVE_MAD
  34.  
  35. /* Maximum number of memory area handles,
  36.    increase this if you run out of handles */
  37. #define MAD_MAX_AREAS 3000
  38. /* Maximum file name length */
  39. #define MAD_MAX_FILE 50
  40. /* Signature for detecting overwrites */
  41. #define MAD_SIGNATURE (('M'<<24)|('a'<<16)|('d'<<8)|('S'))
  42.  
  43. typedef struct {
  44.     int in_use;
  45.     long *start_sig;
  46.     char file [MAD_MAX_FILE];
  47.     int line;
  48.     void *data;
  49.     long *end_sig;
  50. } mad_mem_area;
  51.  
  52. static mad_mem_area mem_areas [MAD_MAX_AREAS];
  53. static void *watch_free_pointer = 0;
  54.  
  55. /* This function is only called by the mad_check function */
  56. static void mad_abort (char *message, int area, char *file, int line)
  57. {
  58.     fprintf (stderr, "MAD: %s in area %d.\r\n", message, area);
  59.     fprintf (stderr, "     Allocated in file \"%s\" at line %d.\r\n",
  60.          mem_areas [area].file, mem_areas [area].line);
  61.     fprintf (stderr, "     Discovered in file \"%s\" at line %d.\r\n",
  62.          file, line);
  63.     fprintf (stderr, "MAD: Core dumping...\r\n");
  64.     kill (getpid (), 3);
  65. }
  66.  
  67. /* Checks all the allocated memory areas.
  68.    This is called everytime memory is allocated or freed.
  69.    You can also call it anytime you think memory might be corrupted. */
  70. void mad_check (char *file, int line)
  71. {
  72.     int i;
  73.  
  74.     for (i = 0; i < MAD_MAX_AREAS; i++){
  75.      if (! mem_areas [i].in_use)
  76.         continue;
  77.     if (*(mem_areas [i].start_sig) != MAD_SIGNATURE)
  78.         mad_abort ("Overwrite error: Bad start signature", i, file, line);
  79.     if (*(mem_areas [i].end_sig) != MAD_SIGNATURE)
  80.         mad_abort ("Overwrite error: Bad end signature", i, file, line);
  81.     }
  82. }
  83.  
  84. /* Allocates a memory area. Used instead of malloc and calloc. */
  85. void *mad_alloc (int size, char *file, int line)
  86. {
  87.     int i;
  88.     char *area;
  89.  
  90.     mad_check (file, line);
  91.  
  92.     for (i = 0; i < MAD_MAX_AREAS; i++){
  93.     if (! mem_areas [i].in_use)
  94.         break;
  95.     }
  96.     if (i >= MAD_MAX_AREAS){
  97.     fprintf (stderr, "MAD: Out of memory area handles. Increase the value of MAD_MAX_AREAS.\r\n");
  98.     fprintf (stderr, "     Discovered in file \"%s\" at line %d.\r\n",
  99.          file, line);
  100.     fprintf (stderr, "MAD: Aborting...\r\n");
  101.     abort ();
  102.     }
  103.  
  104.     mem_areas [i].in_use = 1;
  105.     size = (size + 3) & (~3); /* Alignment */
  106.     area = (char*) malloc (size + 2 * sizeof (long));
  107.     if (!area){
  108.     fprintf (stderr, "MAD: Out of memory.\r\n");
  109.     fprintf (stderr, "     Discovered in file \"%s\" at line %d.\r\n",
  110.          file, line);
  111.     fprintf (stderr, "MAD: Aborting...\r\n");
  112.     abort ();
  113.     }
  114.  
  115.     mem_areas [i].start_sig = (long*) area;
  116.     mem_areas [i].data = (area + sizeof (long));
  117.     mem_areas [i].end_sig = (long*) (area + size + sizeof (long));
  118.     *(mem_areas [i].start_sig) = MAD_SIGNATURE;
  119.     *(mem_areas [i].end_sig) = MAD_SIGNATURE;
  120.  
  121.     if (strlen (file) >= MAD_MAX_FILE)
  122.     file [MAD_MAX_FILE - 1] = 0;
  123.     strcpy (mem_areas [i].file, file);
  124.     mem_areas [i].line = line;
  125.  
  126.     return mem_areas [i].data;
  127. }
  128.  
  129. /* Reallocates a memory area. Used instead of realloc. */
  130. void *mad_realloc (void *ptr, int newsize, char *file, int line)
  131. {
  132.     int i;
  133.     char *area;
  134.     
  135.     mad_check (file, line);
  136.  
  137.     for (i = 0; i < MAD_MAX_AREAS; i++){
  138.      if (! mem_areas [i].in_use)
  139.         continue;
  140.     if (mem_areas [i].data == ptr)
  141.         break;
  142.     }
  143.     if (i >= MAD_MAX_AREAS){
  144.     fprintf (stderr, "MAD: Attempted to realloc unallocated pointer: %ux.\r\n", ptr);
  145.     fprintf (stderr, "     Discovered in file \"%s\" at line %d.\r\n",
  146.          file, line);
  147.     fprintf (stderr, "MAD: Aborting...\r\n");
  148.     abort ();
  149.     }
  150.  
  151.     newsize = (newsize + 3) & (~3); /* Alignment */
  152.     area = (char*) realloc (mem_areas [i].start_sig, newsize + 2 * sizeof (long));
  153.     if (!area){
  154.     fprintf (stderr, "MAD: Out of memory.\r\n");
  155.     fprintf (stderr, "     Discovered in file \"%s\" at line %d.\r\n",
  156.          file, line);
  157.     fprintf (stderr, "MAD: Aborting...\r\n");
  158.     abort ();
  159.     }
  160.  
  161.     mem_areas [i].start_sig = (long*) area;
  162.     mem_areas [i].data = (area + sizeof (long));
  163.     mem_areas [i].end_sig = (long*) (area + newsize + sizeof (long));
  164.     *(mem_areas [i].start_sig) = MAD_SIGNATURE;
  165.     *(mem_areas [i].end_sig) = MAD_SIGNATURE;
  166.  
  167.     if (strlen (file) >= MAD_MAX_FILE)
  168.     file [MAD_MAX_FILE - 1] = 0;
  169.     strcpy (mem_areas [i].file, file);
  170.     mem_areas [i].line = line;
  171.  
  172.     return mem_areas [i].data;
  173. }
  174.  
  175. /* Duplicates a character string. Used instead of strdup. */
  176. char *mad_strdup (char *s, char *file, int line)
  177. {
  178.     char *t;
  179.  
  180.     t = (char *) mad_alloc (strlen (s) + 1, file, line);
  181.     strcpy (t, s);
  182.     return t;
  183. }
  184.  
  185. /* Frees a memory area. Used instead of free. */
  186. void mad_free (void *ptr, char *file, int line)
  187. {
  188.     int i;
  189.     
  190.     mad_check (file, line);
  191.  
  192.     if (watch_free_pointer && ptr == watch_free_pointer){
  193.     printf ("watch free pointer found\n");
  194.     }
  195.     
  196.     if (ptr == NULL){
  197.     fprintf (stderr, "MAD: Attempted to free a NULL pointer in file \"%s\" at line %d.\n",
  198.          file, line);
  199.     return;
  200.     }
  201.  
  202.     for (i = 0; i < MAD_MAX_AREAS; i++){
  203.      if (! mem_areas [i].in_use)
  204.         continue;
  205.     if (mem_areas [i].data == ptr)
  206.         break;
  207.     }
  208.     if (i >= MAD_MAX_AREAS){
  209.     fprintf (stderr, "MAD: Attempted to free an unallocated pointer: %X.\r\n", ptr);
  210.     fprintf (stderr, "     Discovered in file \"%s\" at line %d.\r\n",
  211.          file, line);
  212.     fprintf (stderr, "MAD: Aborting...\r\n");
  213.     abort ();
  214.     }
  215.  
  216.     free (mem_areas [i].start_sig);
  217.     mem_areas [i].in_use = 0;
  218. }
  219.  
  220. /* Outputs a list of unfreed memory areas,
  221.    to be called as a last thing before exiting */
  222. void mad_finalize (char *file, int line)
  223. {
  224.     int i;
  225.     
  226.     mad_check (file, line);
  227.  
  228.     /* Following can be commented out if you don't want to see the
  229.        memory leaks of the Midnight Commander */
  230. #if 1
  231.     for (i = 0; i < MAD_MAX_AREAS; i++){
  232.      if (! mem_areas [i].in_use)
  233.         continue;
  234.     fprintf (stderr, "MAD: Unfreed pointer: %X.\n", mem_areas [i].data);
  235.     fprintf (stderr, "     Allocated in file \"%s\" at line %d.\r\n",
  236.          mem_areas [i].file, mem_areas [i].line);
  237.     fprintf (stderr, "     Discovered in file \"%s\" at line %d.\r\n",
  238.          file, line);
  239.     }
  240. #endif
  241. }
  242.  
  243. #endif /* HAVE_MAD */
  244.